package com.xdhl.fu.member.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xdhl.fu.common.core.constant.CacheConstants;
import com.xdhl.fu.common.core.constant.Constants;
import com.xdhl.fu.common.core.constant.UserConstants;
import com.xdhl.fu.common.core.exception.ServiceException;
import com.xdhl.fu.common.core.utils.JwtUtils;
import com.xdhl.fu.common.core.utils.ServletUtils;
import com.xdhl.fu.common.core.utils.StringUtils;
import com.xdhl.fu.common.core.utils.bean.BeanUtils;
import com.xdhl.fu.common.core.utils.ip.IpUtils;
import com.xdhl.fu.common.security.utils.SecurityUtils;
import com.xdhl.fu.member.domain.MemberBasic;
import com.xdhl.fu.member.domain.MemberLogininfor;
import com.xdhl.fu.member.domain.vo.MemberBasicVO;
import com.xdhl.fu.member.form.RegisterBody;
import com.xdhl.fu.member.service.IMemberAuthService;
import com.xdhl.fu.member.service.IMemberBasicService;
import com.xdhl.fu.member.service.IMemberLogininforService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;

/**
 * 会员登录注册业务实现
 *
 * @author 朱力维
 * @time 2022/6/6 10:31
 */
@Component
public class MemberAuthServiceImpl implements IMemberAuthService {

    @Resource
    private IMemberLogininforService memberLogininforService;

    @Resource
    private IMemberBasicService memberBasicService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Value("${spring.profiles.active}")
    private String springProfilesActive;

    @Override
    public MemberBasicVO login(String username, String password) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password)) {
            throw new ServiceException("用户/密码必须填写");
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            throw new ServiceException("用户密码不在指定范围");
        }
        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH) {
            throw new ServiceException("用户名不在指定范围");
        }
        // 查询用户信息
        LambdaQueryWrapper<MemberBasic> condition = new LambdaQueryWrapper<>();
        condition.eq(MemberBasic::getTelephoneNumber, username)
                .or().eq(MemberBasic::getIdCardNumber, username)
                .or().eq(MemberBasic::getEmail, username);
        MemberBasic member = memberBasicService.getOne(condition);
        if (StringUtils.isNull(member)) {
            throw new ServiceException("登录用户：" + username + " 不存在");
        }

        if (!SecurityUtils.matchesPassword(password, member.getMPassword())) {
            recordLogininfor(member.getDataId(), Constants.LOGIN_FAIL, "用户密码错误");
            throw new ServiceException("用户不存在/密码错误");
        }
        recordLogininfor(member.getDataId(), Constants.LOGIN_SUCCESS, "登录成功");
        MemberBasicVO memberBasicVO = new MemberBasicVO();
        BeanUtils.copyBeanProp(memberBasicVO, member);
        return memberBasicVO;
    }

    @Override
    public MemberBasicVO loginByEmail(String email, String inputAuthCode) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(email, inputAuthCode)) {
            throw new ServiceException("邮箱/验证码必须填写");
        }
        // 验证码如果不是6位 错误
        if (inputAuthCode.length() != 6) {
            throw new ServiceException("请输入6位验证码");
        }
        // 查询用户信息
        LambdaQueryWrapper<MemberBasic> condition = new LambdaQueryWrapper<>();
        condition.eq(MemberBasic::getEmail, email);
        MemberBasic member = memberBasicService.getOne(condition);
        if (StringUtils.isNull(member)) {
            throw new ServiceException("邮箱：" + email + "尚未注册，请注册后重试");
        }
        // 邮箱验证码校验
        String authCode = stringRedisTemplate.opsForValue().get(CacheConstants.EMAIL_PREFIX + email);
        // 邮箱验证码与用户输入不匹配 错误
        if (!"dev".equals(springProfilesActive) && !inputAuthCode.equals(authCode)) {
            throw new ServiceException("邮箱验证码错误");
        }
        recordLogininfor(member.getDataId(), Constants.LOGIN_SUCCESS, "登录成功");
        MemberBasicVO memberBasicVO = new MemberBasicVO();
        BeanUtils.copyBeanProp(memberBasicVO, member);
        return memberBasicVO;
    }

    @Override
    public void logout(String loginName) {
        // 查询用户信息
        LambdaQueryWrapper<MemberBasic> condition = new LambdaQueryWrapper<>();
        condition.eq(MemberBasic::getTelephoneNumber, loginName)
                .or().eq(MemberBasic::getIdCardNumber, loginName)
                .or().eq(MemberBasic::getEmail, loginName);
        MemberBasic member = memberBasicService.getOne(condition);
        recordLogininfor(member.getDataId(), Constants.LOGOUT, "退出成功");
    }

    @Override
    public MemberBasicVO register(RegisterBody registerBody) {
        // 电子邮箱为空 错误
        if (StringUtils.isBlank(registerBody.getEmail())) {
            throw new ServiceException("电子邮箱必须填写");
        }
        // 邮箱验证码为空 错误
        if (StringUtils.isBlank(registerBody.getVerificationCode())) {
            throw new ServiceException("邮箱验证码必须填写");
        }
        // 密码为空 错误
        if (StringUtils.isBlank(registerBody.getMPassword())) {
            throw new ServiceException("密码必须填写");
        }
        // 确认密码为空 错误
        if (StringUtils.isBlank(registerBody.getMRePassword())) {
            throw new ServiceException("确认密码必须填写");
        }
        // 密码如果不在指定范围内 错误
        if (registerBody.getMPassword().length() < UserConstants.PASSWORD_MIN_LENGTH
                || registerBody.getMPassword().length() > UserConstants.PASSWORD_MAX_LENGTH) {
            throw new ServiceException("用户密码不在指定范围");
        }

        if (!registerBody.getMPassword().equals(registerBody.getMRePassword())) {
            throw new ServiceException("两次输入的密码不一致");
        }

        // 验证码如果不是6位 错误
        if (registerBody.getVerificationCode().length() != 6) {
            throw new ServiceException("请输入6位验证码");
        }

        LambdaQueryWrapper<MemberBasic> conditionEmail = new LambdaQueryWrapper();
        conditionEmail.eq(MemberBasic::getEmail, registerBody.getEmail());
        MemberBasic existMember = memberBasicService.getOne(conditionEmail);
        if (null != existMember) {
            throw new ServiceException("邮箱已被占用");
        }
        // 非开发环境下需要进行验证码校验
        if (!"dev".equals(springProfilesActive)) {
            // 邮箱验证码校验
            String authCode = stringRedisTemplate.opsForValue().get(CacheConstants.EMAIL_PREFIX + registerBody.getEmail());
            //邮箱验证码与用户输入不匹配 错误
            if (!registerBody.getVerificationCode().equals(authCode)) {
                throw new ServiceException("邮箱验证码错误");
            }
        }
        // 注册会员信息
        MemberBasic member = new MemberBasic();
        // 密码加密
        member.setMPassword(SecurityUtils.encryptPassword(registerBody.getMPassword()));
        member.setEmail(registerBody.getEmail());
        // 会员等级默认为C 普通会员
        member.setMLevel("C");
        member.setScore(0F);
        member.setCreditLevel(0);
        member.setNationality("CHN");
        // 服务环境默认为 正式环境
        member.setServiceEnv("A");
        member.setCreateBy("");
        member.setCreateTime(LocalDateTime.now());
        member.setUpdateBy("");
        member.setUpdateTime(LocalDateTime.now());
        memberBasicService.save(member);
        member.setCreateBy(member.getDataId());
        member.setUpdateBy(member.getDataId());
        member.setUpdateTime(LocalDateTime.now());
        memberBasicService.updateById(member);
        recordLogininfor(member.getDataId(), Constants.REGISTER, "注册成功");
        MemberBasicVO memberBasicVO = new MemberBasicVO();
        BeanUtils.copyBeanProp(memberBasicVO, member);
        return memberBasicVO;
    }

    @Override
    public MemberBasicVO getInfo() {
        String username = JwtUtils.getUserName(SecurityUtils.getToken());
        LambdaQueryWrapper<MemberBasic> condition = new LambdaQueryWrapper<>();
        condition.eq(MemberBasic::getIdCardNumber, username)
                .or().eq(MemberBasic::getEmail, username)
                .or().eq(MemberBasic::getTelephoneNumber, username);
        MemberBasic member = memberBasicService.getOne(condition);
        MemberBasicVO memberBasicVO = new MemberBasicVO();
        BeanUtils.copyBeanProp(memberBasicVO, member);
        return memberBasicVO;
    }

    @Override
    public void recordLogininfor(String mdataId, String status, String message) {
        MemberLogininfor logininfor = new MemberLogininfor();
        logininfor.setMemberDataId(mdataId);
        logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
        logininfor.setMessage(message);
        logininfor.setCreateBy(mdataId);
        logininfor.setUpdateBy(mdataId);
        // 日志状态
        if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
            logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS);
        } else if (Constants.LOGIN_FAIL.equals(status)) {
            logininfor.setStatus(Constants.LOGIN_FAIL_STATUS);
        }
        memberLogininforService.save(logininfor);
    }
}